module riscv32_alu #(
	parameter [31:0] MASKED_IRQ = 32'h 0000_0000,
	parameter [31:0] LATCHED_IRQ = 32'h ffff_ffff,
	parameter [31:0] PROGADDR_RESET = 32'h 0000_0000,
	parameter [31:0] PROGADDR_IRQ = 32'h 0000_0004,
	parameter [31:0] STACKADDR = 32'h ffff_ffff
) (
	input clk, resetn,
    
	output reg        mem_valid,
	output reg        mem_instr,
	input             mem_ready,

	output reg [31:0] mem_addr,
	output reg [31:0] mem_wdata,
	output reg [ 3:0] mem_wstrb,
	input      [31:0] mem_rdata,
    output reg [31:0] stap,
    output reg        tlb_clean,
    input             tlb_cache,
	// IRQ Interface
	input      [31:0] irq,
	output irq_state,

	// Trace Interface
    input             run_req,
    input             step_req,
    input             halt_req,
    output            halt_ready,
    input             dbg_reg_write_req,
    output reg        dbg_reg_write_resp,
    input      [31:0] dbg_reg_wdata,
    input      [7:0]  dbg_reg_raddr,
    input      [7:0]  dbg_reg_waddr,
    output     [31:0] dbg_reg_data_out,
    input      [11:0] dbg_csr_reg_addr,
    input             dbg_crs_reg_wr,
    output reg        dbg_csr_we_resp,
    output reg [31:0] dbg_csr_data_out,
    input      [31:0] dbg_csr_data_in,
    input             dbg_reset,
	output     [31:0] mret,
	output     [31:0] mcause_o,
    output     [31:0] mie
);

//reg [4:0] reg_raddr;
reg [4:0] rs1_addr;
reg [31:0] reg_rdata1;
reg [4:0] rs2_addr;
reg [31:0] reg_rdata2;

wire [4:0] reg_waddr;
reg [31:0] reg_wdata;


reg reg_we;
reg [31:0] core_reg [0:31];

always @ (posedge clk) begin
    if((reg_we == 1'b1)&&(reg_waddr != 5'd0)) begin
        core_reg[reg_waddr] <= reg_wdata; 
    end
end


// 读寄存器1
always @ (*) begin
    if (rs1_addr == 5'd0) begin
        reg_rdata1 = 32'd0;
    // 如果读地址等于写地址，并且正在写操作，则直接返回写数据
    end else if ((reg_waddr == rs1_addr)&&(reg_we == 1'b1)) begin
        reg_rdata1 = reg_wdata;
    end else begin
        reg_rdata1 = core_reg[rs1_addr];
    end
end
// 读寄存器2
always @ (*) begin
    if (rs2_addr == 5'd0) begin
        reg_rdata2 = 32'd0;
    // 如果读地址等于写地址，并且正在写操作，则直接返回写数据
    end else if ((reg_waddr == rs2_addr)&&(reg_we == 1'b1)) begin
        reg_rdata2 = reg_wdata;
    end else begin
        reg_rdata2 = core_reg[rs2_addr];
    end
end

//实现了检测irq上升沿功能
reg [31:0] irq_last;
always @(posedge clk) begin
    irq_last <= irq;
end
wire [31:0] irq_posedge;
assign irq_posedge = (~irq_last)&irq;

//下面是risc-v CPU逻辑
reg [31:0] core_pc;

reg [31:0] irq_mask;
reg [31:0] mstatus;
reg [31:0] mret_reg;
reg [31:0] mcause;
reg [31:0] dpc;
reg [7:0]  dcsr;
reg [2:0] cpu_state;

reg [31:0] op1num;
reg [31:0] op2num;

wire[31:0] op1_add_op2_res;
wire op1_ge_op2_signed;
wire op1_ge_op2_unsigned;
wire op1_eq_op2;

//加法
assign op1_add_op2_res = op1num + op2num;
// 有符号数比较
assign op1_ge_op2_signed = $signed(op1num) >= $signed(op2num);
// 无符号数比较
assign op1_ge_op2_unsigned = (op1num >= op2num) ? 1'b1 : 1'b0;
assign op1_eq_op2 = (op1num == op2num) ? 1'b1 : 1'b0;

wire [31:0] num_shift_right_res;
assign num_shift_right_res = op1num >> op2num[4:0];

wire [31:0] num_shift_left_res;
assign num_shift_left_res = op1num << op2num[4:0];

wire [31:0] num1_sub_num2;
assign num1_sub_num2 = op1num - op2num;

wire [31:0] num_xor_res;
assign num_xor_res = op1num ^ op2num;

wire [31:0] num_or_res;
assign num_or_res = op1num | op2num;

wire [31:0] num_and_res;
assign num_and_res = op1num & op2num;

wire [31:0] num_sra_shift_right_res;
assign num_sra_shift_right_res = (num_shift_right_res | ({32{op1num[31]}} & (~(32'hffffffff >> op2num[4:0]))));

reg [31:0] mem_addr_add;
wire [31:0] mem_addr_add_res;
assign mem_addr_add_res = op1num + mem_addr_add;
wire [1:0] mem_raddr_index;
assign mem_raddr_index = mem_addr_add_res & 2'b11;

wire [1:0] mem_waddr_index;
assign mem_waddr_index = mem_addr_add_res & 2'b11;


parameter cpu_fetch0                  =   3'd0;
parameter cpu_fetch1                  =   3'd1;
parameter cpu_inst_decode             =   3'd2;//等待指令译码完成
parameter cpu_state_ld_rs             =   3'd3;
parameter cpu_state_exec              =   3'd4;
parameter cpu_state_stmem             =   3'd5;
parameter cpu_state_ldmem             =   3'd6;
parameter cpu_statehalt               =   3'd7;

parameter LUI_INS                 =   7'b011_0111;
parameter AUIPC_INS               =   7'b001_0111;
parameter J_INS                   =   7'b110_1111;
parameter JALR_INS                =   7'b110_0111;
parameter B_TYPE_INS              =   7'b110_0011;
parameter I_TYPE_INS              =   7'b001_0011;
parameter L_TYPE_INS              =   7'b000_0011;
parameter S_TYPE_INS              =   7'b010_0011;
parameter R_TYPE_INS              =   7'b011_0011;
parameter MRS_TYPE_INS            =   7'b100_0011;
parameter MSR_TYPE_INS            =   7'b100_1011;
parameter IRQ_TYPE_INS            =   7'b100_1111;
parameter CSR_TYPE_INS            =   7'b111_0011;

reg [3:0] ins_cnt;
reg [31:0] temp_data;

wire [31:0] jump_res;
reg [31:0] jump_offset;
assign jump_res = core_pc + jump_offset;

reg irq_active;
wire irq_request;
assign irq_state = irq_active;
assign mret = mret_reg;
assign mie = irq_mask;
reg [31:0] mtvec;
reg [31:0] instr_latch;


reg [31:0] i_type_imme;
always @(posedge clk) begin
    if(!resetn)begin
        i_type_imme <= 32'h0;
    end
    else begin
        i_type_imme <= {{20{instr_latch[31]}}, instr_latch[31:20]};
    end
end

reg [31:0] b_type_imme;
always @(posedge clk) begin
    if(!resetn)begin
        b_type_imme <= 32'h0;
    end
    else  begin
        b_type_imme <= {{20{instr_latch[31]}},instr_latch[7],instr_latch[30:25],instr_latch[11:8],1'b0};
    end
end

reg [31:0] l_type_imme;
always @(posedge clk) begin
    if(!resetn)begin
        l_type_imme <= 32'h0;
    end
    else  begin
        l_type_imme <= {{20{instr_latch[31]}}, instr_latch[31:20]};
    end
end

reg [31:0] s_type_imme;
always @(posedge clk) begin
    if(!resetn)begin
        s_type_imme <= 32'h0;
    end
    else  begin
        s_type_imme <= {{20{instr_latch[31]}}, instr_latch[31:25], instr_latch[11:7]};
    end
end
reg [31:0] u_type_imme;
always @(posedge clk) begin
    if(!resetn)begin
        u_type_imme <= 32'h0;
    end
    else begin
        u_type_imme <= {instr_latch[31:12],12'h0};
    end
end
reg [31:0] jal_type_imme;
always @(posedge clk) begin
    if(!resetn)begin
        jal_type_imme <= 32'h0;
    end
    else begin
        jal_type_imme <= {{12{instr_latch[31]}}, instr_latch[19:12], instr_latch[20], instr_latch[30:21], 1'b0};
    end
end
reg [31:0] jalr_type_imme;
always @(posedge clk) begin
    if(!resetn)begin
        jalr_type_imme <= 32'h0;
    end
    else begin
        jalr_type_imme <= {{20{instr_latch[31]}}, instr_latch[31:20]};
    end
end
reg [31:0] csr_type_imme;
always @(posedge clk) begin
    if(!resetn)begin
        csr_type_imme <= 32'h0;
    end
    else begin
        csr_type_imme <= {{26{instr_latch[19]}}, instr_latch[19:15]};
    end
end
always @(posedge clk) begin
    if(!resetn)begin
        rs1_addr <= 32'h0;
    end
    else if(cpu_state != cpu_statehalt)begin
        rs1_addr <= {instr_latch[19:15]};
    end
    else begin
        if(dbg_reg_raddr < 8'd32)begin
            rs1_addr <= dbg_reg_raddr[4:0];
        end
        else begin
            rs1_addr <= 5'd0;
        end
    end
end
always @(posedge clk) begin
    if(!resetn)begin
        rs2_addr <= 32'h0;
    end
    else begin
        rs2_addr <= {instr_latch[24:20]};
    end
end
reg [4:0] rd_addr;
always @(posedge clk) begin
    if(!resetn)begin
        rd_addr <= 5'h0;
    end
    else if(cpu_state != cpu_statehalt)begin
        rd_addr <= {instr_latch[11:7]};
    end
    else begin
         if(dbg_reg_waddr < 8'd32)begin
            rd_addr <= dbg_reg_waddr[4:0];
        end
        else begin
            rd_addr <= 5'd0;
        end
    end
end
assign reg_waddr = rd_addr;
reg [11:0] csr_addr;
always @(posedge clk) begin
    if(!resetn)begin
        csr_addr <= 12'h0;
    end
    else begin
        csr_addr <= {instr_latch[31:20]};
    end
end
wire lui_ins_flag;
assign lui_ins_flag    = (instr_latch[6:0] == LUI_INS);
wire auipc_ins_flag;
assign auipc_ins_flag  = (instr_latch[6:0] == AUIPC_INS);
wire j_type_ins_flag;
assign j_type_ins_flag = (instr_latch[6:0] == J_INS);
wire jalr_ins_flag;
assign jalr_ins_flag   = (instr_latch[6:0] == JALR_INS);
wire b_type_ins_flag;
assign b_type_ins_flag = (instr_latch[6:0] == B_TYPE_INS);
wire i_type_ins_flag;
assign i_type_ins_flag = (instr_latch[6:0] == I_TYPE_INS);
wire l_type_ins_flag;
assign l_type_ins_flag = (instr_latch[6:0] == L_TYPE_INS);
wire s_type_ins_flag;
assign s_type_ins_flag = (instr_latch[6:0] == S_TYPE_INS);
wire r_type_ins_flag;
assign r_type_ins_flag = (instr_latch[6:0] == R_TYPE_INS);
wire csr_ins_flag;
assign csr_ins_flag    = (instr_latch[6:0] == CSR_TYPE_INS );
reg lui_ins;
reg auipc_ins;
reg j_type_ins;
reg jalr_ins;
reg b_type_ins;
reg i_type_ins;
reg l_type_ins;
reg s_type_ins;
reg r_type_ins;
reg csr_ins;
always@(posedge clk )begin
    if(!resetn)begin
        lui_ins <= 1'b0;
        auipc_ins <= 1'b0;
        j_type_ins <= 1'b0;
        jalr_ins <= 1'b0;
        b_type_ins <= 1'b0;
        i_type_ins <= 1'b0;
        l_type_ins <= 1'b0;
        s_type_ins <= 1'b0;
        r_type_ins <= 1'b0;
        csr_ins <= 1'b0;
    end
    else begin
        lui_ins    <= lui_ins_flag;
        auipc_ins  <= auipc_ins_flag;
        j_type_ins <= j_type_ins_flag;
        jalr_ins   <= jalr_ins_flag;
        b_type_ins <= b_type_ins_flag;
        i_type_ins <= i_type_ins_flag;
        l_type_ins <= l_type_ins_flag;
        s_type_ins <= s_type_ins_flag;
        r_type_ins <= r_type_ins_flag;
        csr_ins    <= csr_ins_flag;
    end
end

//J指令
reg is_jalr_ins;
//B指令
reg is_beq_ins;
reg is_bne_ins;
reg is_blt_ins;
reg is_bge_ins;
reg is_bltu_ins;
reg is_bgeu_ins;
//L指令
reg is_lb_ins;
reg is_lh_ins;
reg is_lw_ins;
reg is_lbu_ins;
reg is_lhu_ins;
//S指令
reg is_sb_ins;
reg is_sh_ins;
reg is_sw_ins;
//I指令
reg is_addi_ins;
reg is_slti_ins;
reg is_sltiu_ins;
reg is_xori_ins;
reg is_ori_ins;
reg is_andi_ins;
reg is_slli_ins;
reg is_srli_ins;
reg is_srai_ins;
//R指令
reg is_add_ins;
reg is_sub_ins;
reg is_sll_ins;
reg is_slt_ins;
reg is_sltu_ins;
reg is_xor_ins;
reg is_srl_ins;
reg is_sra_ins;
reg is_or_ins;
reg is_and_ins;
//CSR指令
reg is_ecall_ebreak_mret;
reg is_csrrw_ins;
reg is_csrrs_ins;

always@(posedge clk )begin
    if(!resetn)begin
        is_jalr_ins  <= 1'b0;
        is_beq_ins   <= 1'b0;
        is_bne_ins   <= 1'b0;
        is_blt_ins   <= 1'b0;
        is_bge_ins   <= 1'b0;
        is_bltu_ins  <= 1'b0;
        is_bgeu_ins  <= 1'b0;
        is_lb_ins    <= 1'b0;
        is_lh_ins    <= 1'b0;
        is_lw_ins    <= 1'b0;
        is_lbu_ins   <= 1'b0;
        is_lhu_ins   <= 1'b0;
        is_sb_ins    <= 1'b0;
        is_sh_ins    <= 1'b0;
        is_sw_ins    <= 1'b0;
        is_addi_ins  <= 1'b0;
        is_slti_ins  <= 1'b0;
        is_sltiu_ins <= 1'b0;
        is_xori_ins  <= 1'b0;
        is_ori_ins   <= 1'b0;
        is_andi_ins  <= 1'b0;
        is_slli_ins  <= 1'b0;
        is_srli_ins  <= 1'b0;
        is_srai_ins  <= 1'b0;
        is_add_ins   <= 1'b0;
        is_sub_ins   <= 1'b0;
        is_sll_ins   <= 1'b0;
        is_slt_ins   <= 1'b0;
        is_sltu_ins  <= 1'b0;
        is_xor_ins   <= 1'b0;
        is_srl_ins   <= 1'b0;
        is_sra_ins   <= 1'b0;
        is_or_ins    <= 1'b0;
        is_and_ins   <= 1'b0;
        is_ecall_ebreak_mret <= 1'b0;
        is_csrrw_ins <= 1'b0;
        is_csrrs_ins <= 1'b0;
    end
    else begin
        is_jalr_ins  <= jalr_ins_flag   & (instr_latch[14:12] == 3'b000);
        is_beq_ins   <= b_type_ins_flag & (instr_latch[14:12] == 3'b000);
        is_bne_ins   <= b_type_ins_flag & (instr_latch[14:12] == 3'b001);
        is_blt_ins   <= b_type_ins_flag & (instr_latch[14:12] == 3'b100);
        is_bge_ins   <= b_type_ins_flag & (instr_latch[14:12] == 3'b101);
        is_bltu_ins  <= b_type_ins_flag & (instr_latch[14:12] == 3'b110);
        is_bgeu_ins  <= b_type_ins_flag & (instr_latch[14:12] == 3'b111);
        is_lb_ins    <= l_type_ins_flag & (instr_latch[14:12] == 3'b000);
        is_lh_ins    <= l_type_ins_flag & (instr_latch[14:12] == 3'b001);
        is_lw_ins    <= l_type_ins_flag & (instr_latch[14:12] == 3'b010);
        is_lbu_ins   <= l_type_ins_flag & (instr_latch[14:12] == 3'b100);
        is_lhu_ins   <= l_type_ins_flag & (instr_latch[14:12] == 3'b101);
        is_sb_ins    <= s_type_ins_flag & (instr_latch[14:12] == 3'b000);
        is_sh_ins    <= s_type_ins_flag & (instr_latch[14:12] == 3'b001);
        is_sw_ins    <= s_type_ins_flag & (instr_latch[14:12] == 3'b010);
        is_addi_ins  <= i_type_ins_flag & (instr_latch[14:12] == 3'b000);
        is_slti_ins  <= i_type_ins_flag & (instr_latch[14:12] == 3'b010);
        is_sltiu_ins <= i_type_ins_flag & (instr_latch[14:12] == 3'b011);
        is_xori_ins  <= i_type_ins_flag & (instr_latch[14:12] == 3'b100);
        is_ori_ins   <= i_type_ins_flag & (instr_latch[14:12] == 3'b110);
        is_andi_ins  <= i_type_ins_flag & (instr_latch[14:12] == 3'b111);
        is_slli_ins  <= i_type_ins_flag & (instr_latch[14:12] == 3'b001);
        is_srli_ins  <= i_type_ins_flag & (instr_latch[14:12] == 3'b101) & (instr_latch[31:25] == 7'b0000000);
        is_srai_ins  <= i_type_ins_flag & (instr_latch[14:12] == 3'b101) & (instr_latch[31:25] == 7'b0100000);
        is_add_ins   <= r_type_ins_flag & (instr_latch[14:12] == 3'b000) & (instr_latch[31:25] == 7'b0000000);
        is_sub_ins   <= r_type_ins_flag & (instr_latch[14:12] == 3'b000) & (instr_latch[31:25] == 7'b0100000);
        is_sll_ins   <= r_type_ins_flag & (instr_latch[14:12] == 3'b001);
        is_slt_ins   <= r_type_ins_flag & (instr_latch[14:12] == 3'b010);
        is_sltu_ins  <= r_type_ins_flag & (instr_latch[14:12] == 3'b011);
        is_xor_ins   <= r_type_ins_flag & (instr_latch[14:12] == 3'b100);
        is_srl_ins   <= r_type_ins_flag & (instr_latch[14:12] == 3'b101) & (instr_latch[31:25] == 7'b0000000);
        is_sra_ins   <= r_type_ins_flag & (instr_latch[14:12] == 3'b101) & (instr_latch[31:25] == 7'b0100000);
        is_or_ins    <= r_type_ins_flag & (instr_latch[14:12] == 3'b110);
        is_and_ins   <= r_type_ins_flag & (instr_latch[14:12] == 3'b111);
        is_ecall_ebreak_mret <= csr_ins_flag & (instr_latch[14:12] == 3'b000);
        is_csrrw_ins <= csr_ins_flag & (instr_latch[14:12] == 3'b001);
        is_csrrs_ins <= csr_ins_flag & (instr_latch[14:12] == 3'b010);
    end
end

reg [31:0] core_next_pc;

reg ins_ready_1_clk;//取指令完成标志延时一个时钟周期
always@(posedge clk) begin
    ins_ready_1_clk <= mem_ready&mem_instr;
end

reg valid_inst;//细节判断指令是否合法
always@(posedge clk) begin
    if(!resetn)begin
        valid_inst <= 1'b0;
    end
    else begin
        valid_inst <= is_jalr_ins | is_beq_ins | is_bne_ins | is_blt_ins | is_bge_ins | is_bltu_ins | is_bgeu_ins //JALR指令和B指令
        | is_lb_ins | is_lh_ins | is_lw_ins | is_lbu_ins | is_lhu_ins | is_sb_ins | is_sh_ins  |is_sw_ins //L指令和S指令
        | is_addi_ins |is_slti_ins | is_sltiu_ins | is_xori_ins | is_ori_ins | is_andi_ins | is_slli_ins | is_srli_ins | is_srai_ins //I指令
        | is_add_ins | is_sub_ins | is_sll_ins | is_slt_ins | is_sltu_ins | is_xor_ins | is_srl_ins | is_sra_ins | is_or_ins | is_and_ins //R指令
        | is_ecall_ebreak_mret | is_csrrw_ins | is_csrrs_ins//CSR指令
        | lui_ins | auipc_ins | j_type_ins;
    end
end
assign halt_ready = (cpu_state == cpu_statehalt);
assign dbg_reg_data_out = (dbg_reg_raddr < 8'd32) ? reg_rdata1 : core_pc;
reg [31:0] irq_pending;
always@(posedge clk )begin
    if(!resetn)begin
        core_pc <= PROGADDR_RESET;
        irq_mask <= ~32'hf0000000;
        cpu_state <= cpu_fetch0;
        irq_active <= 1'b0;
        mcause <= 32'h0;
        irq_pending <= 32'h0;
        reg_we <= 1'b0;
        mem_valid <= 1'b0;
        mem_instr <= 1'b0;
        mem_addr <= 32'h0;
        mtvec <= PROGADDR_IRQ;
        instr_latch <= 32'h0;
        dcsr <= 8'h0;
        stap <= 32'h0;
        tlb_clean <= 1'b0;
        dbg_reg_write_resp <= 1'b0;
        dbg_csr_we_resp <= 1'b0;
    end
    else begin
        dbg_csr_we_resp <= 1'b0;
        dbg_reg_write_resp <= 1'b0;
        tlb_clean <= 1'b0;
        reg_we <= 1'b0;
        ins_cnt <= 4'd0;
        irq_active <= irq_active;
        
        if(irq_mask != 32'h0)begin
            irq_pending = irq_posedge&irq_mask;//irq;
        end
        else begin
            irq_pending = 32'h0;
        end
        mcause[27:0] <= mcause[27:0] | irq_pending[27:0];
             
        case(cpu_state)
            cpu_fetch0:begin
                core_next_pc <= core_pc + 4'd4;
                mem_valid <= 1'b0;
                mem_wstrb <= 4'b0000;
                jump_offset <= 32'h0;
                mem_instr <= 1'b0;
                if(dcsr[6])begin
                    if(dcsr[7])begin
                        dcsr[6] <= 1'b0;
                    end
                    else begin
                        if((dcsr[0] == 1'b0)&&(mcause[30] == 1'b0)&&(dcsr[1] == 1'b0))begin
                            dcsr[6] <= 1'b0;
                            mcause[30] <= 1'b1;
                        end
                        else begin
                            dcsr <= dcsr;
                            mcause <= mcause;
                        end
                    end
                end
                reg_we <= 1'b0;//无论怎么此处必须将reg_we 置 0
                if((halt_req == 1'b1) || (dcsr[7:6] == 2'b10)) begin
                    reg_we <= 1'b0;
                    ins_cnt <= 4'd0;
                    cpu_state <= cpu_statehalt;
                end
                else begin
                    cpu_state <= cpu_fetch1;
                end
                if(!irq_active && |(mcause&~irq_mask))begin
                    mret_reg <= core_pc;//异步中断
                    if(mcause[30]) begin
                        dcsr[1] <= 1'b1;
                        core_pc <= mtvec + 32'h4;
                        mem_addr <= mtvec + 32'h4;
                    end
                    else begin
                        core_pc <= mtvec;
                        mem_addr <= mtvec;
                    end
                    irq_active <= 1'b1;    
                end
                else begin
                    mem_addr <= core_pc;
                end
            end
            cpu_fetch1:begin
                core_pc <= core_pc;
                mem_valid <= 1'b1;
                mem_instr <= 1'b1;
                cpu_state <= cpu_state;
                if(mem_ready)begin
                    mem_valid <= 1'b0;
                    mem_instr <= 1'b0;
                    instr_latch <= mem_rdata;//采用指令锁存故，指令会晚一排
                    cpu_state <= cpu_inst_decode;
                end
            end
            cpu_inst_decode:begin
                cpu_state <= cpu_state_ld_rs;//等待指令译码完成
            end
            cpu_state_ld_rs:begin
                mem_valid = 1'b0;
                core_pc <= core_pc;
                cpu_state <= cpu_state_ld_rs;
                (* parallel_case *)
                case (1'b1)
                    !valid_inst:begin
                        cpu_state <= cpu_state_exec;
                    end
                    j_type_ins:begin//j指令
                        core_pc <= jal_type_imme + core_pc;
                        cpu_state <= cpu_fetch0;
                    end
                    lui_ins || auipc_ins:begin//U指令
                        op1num <=  lui_ins ? 0 : core_pc;
                        op2num <= u_type_imme;
                        cpu_state <= cpu_state_exec;
                    end
                    b_type_ins :begin//b指令
                        op1num <= reg_rdata1;
                        op2num <= reg_rdata2;
                        jump_offset <= b_type_imme;//B指令可能跳转地址
                        cpu_state <= cpu_state_exec;
                    end
                    r_type_ins: begin//r指令
                        op1num <= reg_rdata1;
                        op2num <= reg_rdata2;
                        cpu_state <= cpu_state_exec;
                    end
                    i_type_ins :begin//i指令
                        op1num <= reg_rdata1;
                        op2num <= i_type_imme;
                        cpu_state <= cpu_state_exec;
                    end
                    s_type_ins : begin
                        op1num <= reg_rdata1;
                        op2num <= s_type_imme;
                        mem_addr_add <= s_type_imme;
                        
                        cpu_state <= cpu_state_stmem;
                    end
                    jalr_ins :begin
                        op1num <= reg_rdata1;//jalr 操作数1；
                        op2num <= jalr_type_imme;//跳转地址从加法操作结果得出
                        cpu_state <= cpu_state_exec;
                    end
                    l_type_ins :begin
                        op1num <= reg_rdata1;
                        mem_addr_add <= l_type_imme;
                        cpu_state <= cpu_state_ldmem;//等到进入cpu_state_ldmem状态时在请求接收数据因为需要延时一个clk
                    end
                    csr_ins:begin
                        op1num <= reg_rdata1;
                        cpu_state <= cpu_state_exec;
                    end
                endcase
            end
            cpu_state_exec:begin
                mem_valid = 1'b0;
                reg_we    <= 1'b1;
                core_pc <= core_next_pc;
                cpu_state <= cpu_fetch0;                                
                (* parallel_case *)
                case(1'b1)
                    !valid_inst:begin
                        reg_we    <= 1'b0;
                        cpu_state <= cpu_fetch0;
                        mcause[29] <= 1;
                        mret_reg = core_pc;//同步中断
                        core_pc <= mtvec; 
                        irq_active <= 1'b1;//直接进中断
                    end
                    is_add_ins || is_addi_ins || lui_ins || auipc_ins :begin
                        reg_wdata <= op1_add_op2_res;
                    end
                    is_sub_ins:begin
                    reg_wdata <= num1_sub_num2;
                    end
                    is_sll_ins || is_slli_ins:begin
                        reg_wdata <= num_shift_left_res;
                    end
                    is_sra_ins || is_srai_ins:begin
                        reg_wdata <= num_sra_shift_right_res;
                    end
                    is_srl_ins || is_srli_ins:begin
                        reg_wdata <= num_shift_right_res;
                    end
                    is_slt_ins || is_slti_ins:begin
                        if(op1_ge_op2_signed==1'b0) begin
                            reg_wdata <= 32'h00000001;
                        end
                        else begin
                            reg_wdata <= 32'h00000000;
                        end
                    end
                    is_sltu_ins || is_sltiu_ins :begin
                        if(op1_ge_op2_unsigned==1'b0) begin
                            reg_wdata <= 32'h00000001;
                        end
                        else begin
                            reg_wdata <= 32'h00000000;
                        end
                    end
                    is_xor_ins || is_xori_ins :begin
                        reg_wdata <= num_xor_res;
                    end
                    is_or_ins || is_ori_ins :begin
                        reg_wdata <= num_or_res;
                    end
                    is_and_ins || is_andi_ins :begin
                        reg_wdata <= num_and_res;
                    end
                    is_beq_ins:begin
                        reg_we    <= 1'b0;
                        if(op1_eq_op2==1'b1)begin
                            core_pc <= jump_res;
                        end
                    end
                    is_bne_ins:begin
                        reg_we    <= 1'b0;
                        if(op1_eq_op2 != 1'b1)begin
                            core_pc <= jump_res;                            
                        end
                    end
                    is_blt_ins:begin
                        reg_we    <= 1'b0;
                        if(op1_ge_op2_signed == 1'b0)begin
                            core_pc <= jump_res;
                        end
                    end
                    is_bge_ins:begin
                        reg_we    <= 1'b0;
                        if(op1_ge_op2_signed==1'b1)begin
                            core_pc <= jump_res;
                        end
                    end
                    is_bltu_ins:begin
                        reg_we    <= 1'b0;
                        if(op1_ge_op2_unsigned == 1'b0)begin
                            core_pc <= jump_res;
                        end
                    end
                    is_bgeu_ins:begin
                        reg_we    <= 1'b0;
                        if(op1_ge_op2_unsigned==1'b1)begin
                            core_pc <= jump_res;
                        end
                    end
                    j_type_ins :begin
                        core_pc <= jump_res;
                        reg_wdata <= core_next_pc;
                    end
                    jalr_ins :begin
                        core_pc <= op1_add_op2_res;
                        reg_wdata <= core_next_pc;
                    end
                    
                    is_ecall_ebreak_mret :begin
                        reg_we    <= 1'b0;
                        case(csr_addr)
                            12'h120:begin//sfence.vma清除mmu tlb
                                if(tlb_cache) begin
                                    tlb_clean <= 1'b1;//清除tlb请求
                                    cpu_state <= cpu_state_exec;
                                end
                                else begin
                                    tlb_clean <= 1'b0;
                                    cpu_state <= cpu_fetch0;//tlb clean finish
                                end
                            end
                            12'h102:begin//sret
                                //待写逻辑
                            end
                            12'h7b2:begin//dret
                                dcsr[1] <= 1'b0;
                                irq_active <= 1'b0;
                                core_pc <= mret_reg;
                            end
                            12'h302:begin//mret
                                irq_active <= 1'b0;
                                core_pc <= mret_reg;
                            end
                            12'h000:begin//ecall
                                mcause[31] <= 1;
                                mret_reg = core_pc;//同步中断
                                core_pc <= mtvec; 
                                irq_active <= 1'b1;//直接进中断
                            end
                            12'h001:begin//ebreak
                                if(dcsr[0] == 1'b0) begin
                                    mcause[30] <= 1;
                                    dcsr[1] <= 1'b1;
                                    mret_reg = core_pc;//同步中断
                                    core_pc <= mtvec + 32'h4;
                                    irq_active <= 1'b1;//直接进中断
                                end
                                else begin
                                    core_pc <= core_pc;
                                    cpu_state <= cpu_statehalt;
                                end
                            end
                        endcase
                    end
                    is_csrrw_ins :begin
                        if(rs1_addr!=5'h0) begin
                            case(csr_addr)
                                12'h180:begin
                                    stap <= op1num;
                                end
                                12'h7b0:begin//dcsr
                                    dcsr <= op1num[7:0];//待写逻辑
                                end
                                12'h7b1:begin//dpc
                                    dpc <= op1num;//待写逻辑
                                end
                                12'h341:begin//mret_reg --> mepc
                                    mret_reg <= op1num;
                                end
                                12'h342:begin//mcause --> mcause
                                    mcause <= op1num;
                                end
                                12'h304:begin//irq_mask --> mie
                                    irq_mask <= op1num;
                                end
                                12'h305:begin
                                    mtvec <= op1num;
                                end
                                12'h300:begin//mstatus
                                    mstatus <= op1num;
                                end
                            endcase
                        end
                        if(rd_addr == 12'h0) begin
                            reg_we <= 1'b0;
                        end
                        else begin
                            reg_we <= 1'b1;
                            case(csr_addr)
                                12'h180:begin
                                    reg_wdata <= stap;
                                end
                                12'h7b0:begin//dcsr
                                    reg_wdata <= {24'b0,dcsr[7:0]};//待写逻辑
                                end
                                12'h7b1:begin//dpc
                                    reg_wdata <= dpc;//待写逻辑
                                end
                                12'h341:begin//mret_reg --> mepc
                                    reg_wdata <= mret_reg;
                                end
                                12'h342:begin//mcause --> mcause
                                    reg_wdata <= mcause;
                                end
                                12'h304:begin//irq_mask --> mie
                                    reg_wdata <= irq_mask;
                                end
                                12'h305:begin
                                    reg_wdata <= mtvec;
                                end
                                12'h300:begin//mstatus
                                    reg_wdata <= mstatus;
                                end
                            endcase
                        end
                    end                    
                    is_csrrs_ins :begin
                        if(rs1_addr!=5'h0)begin
                            case(csr_addr)
                                12'h7b0:begin//dcsr
                                    dcsr <= op1num[7:0] | dcsr;//待写逻辑
                                end
                                12'h180:begin
                                    stap <= stap | op1num;
                                end
                                12'h7b1:begin//dpc
                                    dpc <= dpc | op1num;//待写逻辑
                                end
                                12'h341:begin//mret_reg --> mepc
                                    mret_reg <= op1num|mret_reg;
                                end
                                12'h342:begin//mcause --> mcause
                                    mcause <= op1num|mcause;
                                end
                                12'h304:begin//irq_mask --> mie
                                    irq_mask <= op1num|irq_mask;
                                end
                                12'h305:begin
                                    mtvec <= op1num|mtvec;
                                end
                                12'h300:begin//mstatus
                                    mstatus <= op1num|mstatus;
                                end
                            endcase
                        end
                        if(rd_addr == 12'h0) begin
                            reg_we    <= 1'b0;
                        end
                        else begin
                            reg_we <= 1'b1;
                            case(csr_addr)
                                12'h7b0:begin//dcsr
                                    reg_wdata <= {24'b0,dcsr[7:0]};//待写逻辑
                                end
                                12'h180:begin
                                    reg_wdata <= stap;
                                end
                                12'h7b1:begin//dpc
                                    reg_wdata <= dpc;//待写逻辑
                                end
                                12'h341:begin//mret_reg --> mepc
                                    reg_wdata <= mret_reg;
                                end
                                12'h342:begin//mcause --> mcause
                                    reg_wdata <= mcause;
                                end
                                12'h304:begin//irq_mask --> mie
                                    reg_wdata <= irq_mask;
                                end
                                12'h305:begin
                                    reg_wdata <= mtvec;
                                end
                                12'h300:begin//mstatus
                                    reg_wdata <= mstatus;
                                end
                            endcase
                        end
                    end 
                endcase
            end
            cpu_state_stmem:begin
                mem_valid <= 1'b1;
                mem_addr <= op1_add_op2_res;
                mem_wdata <= mem_wdata;
                (* parallel_case, full_case *)
                case (1'b1)
                    is_sb_ins:begin
                        mem_wdata <= {4{reg_rdata2[7:0]}};
                        case (mem_waddr_index)
                        2'b00: begin
                            mem_wstrb <= 4'b0001;
                        end
                        2'b01: begin
                            mem_wstrb <= 4'b0010;
                        end
                        2'b10: begin
                            mem_wstrb <= 4'b0100;
                        end
                        default: begin
                            mem_wstrb <= 4'b1000;
                        end
                        endcase
                    end
                    is_sh_ins:begin
                        mem_wdata <= {2{reg_rdata2[15:0]}};
                        if (mem_waddr_index == 2'b00) begin
                            mem_wstrb <= 4'b0011;
                        end else begin
                            mem_wstrb <= 4'b1100;
                        end
                    end
                    is_sw_ins:begin
                        mem_wstrb <= 4'b1111;
                        mem_wdata <= reg_rdata2;
                    end
                endcase
                if(mem_ready) begin
                    mem_valid <= 1'b0;
                    mem_wstrb <= 4'b0000;//置为0
                    cpu_state <= cpu_fetch0;
                    core_pc <= core_next_pc;
                end
            end
            cpu_state_ldmem:begin
                mem_valid <= 1'b1;//置1请求数据
                mem_addr  <= mem_addr_add_res;//传输地址
                if(mem_ready) begin
                    mem_valid <= 0;
                    core_pc <= core_next_pc;
                    cpu_state <= cpu_fetch0;
                    reg_we    <= 1'b1;
                    (* parallel_case*)
                    case(1'b1)
                        is_lb_ins:begin
                            case(mem_raddr_index)
                                2'b00: begin
                                    reg_wdata <= {{24{mem_rdata[7]}}, mem_rdata[7:0]};
                                end
                                2'b01: begin
                                    reg_wdata <= {{24{mem_rdata[15]}}, mem_rdata[15:8]};
                                end
                                2'b10: begin
                                    reg_wdata <= {{24{mem_rdata[23]}}, mem_rdata[23:16]};
                                end
                                default: begin
                                    reg_wdata <= {{24{mem_rdata[31]}}, mem_rdata[31:24]};
                                end
                            endcase
                        end
                        is_lh_ins:begin
                            if (mem_raddr_index == 2'b0) begin
                                reg_wdata <= {{16{mem_rdata[15]}}, mem_rdata[15:0]};
                            end
                            else begin
                                reg_wdata <= {{16{mem_rdata[31]}}, mem_rdata[31:16]};
                            end
                        end
                        is_lw_ins:begin
                            reg_wdata <= mem_rdata;
                        end
                        is_lbu_ins:begin
                            case(mem_raddr_index)
                                2'b00: begin
                                    reg_wdata <= {24'h0, mem_rdata[7:0]};
                                end
                                2'b01: begin
                                    reg_wdata <= {24'h0, mem_rdata[15:8]};
                                end
                                2'b10: begin
                                    reg_wdata <= {24'h0, mem_rdata[23:16]};
                                end
                                default: begin
                                    reg_wdata <= {24'h0, mem_rdata[31:24]};
                                end
                            endcase
                        end
                        is_lhu_ins:begin
                            if (mem_raddr_index == 2'b0) begin
                                reg_wdata <= {16'h0, mem_rdata[15:0]};
                            end
                            else begin
                                reg_wdata <= {16'h0, mem_rdata[31:16]};
                            end
                        end
                    endcase
                end
            end
            cpu_statehalt:begin
                cpu_state <= cpu_state;
                reg_we <= 1'b0;
                mem_valid <= 1'b0;
                mem_addr <= 32'h0;
                mem_instr <= 1'b0;
                mem_wstrb <= 4'b0000;
                dbg_reg_write_resp <= 1'b0;
                dbg_csr_we_resp <= 1'b0;
                if(run_req) begin
                    dcsr[7:6] <= 2'b00;
                    cpu_state <= cpu_fetch0;
                end
                if(step_req) begin
                    dcsr[7:6] <= 2'b11;
                    cpu_state <= cpu_fetch0;
                end
                if(!dbg_reset) begin
                    core_pc <= PROGADDR_RESET;
                    irq_mask <= ~32'hf0000000;
                    irq_active <= 1'b0;
                    mcause <= 32'h0;
                    irq_pending <= 32'h0;
                    reg_we <= 1'b0;
                    mem_valid <= 1'b0;
                    mem_instr <= 1'b0;
                    mem_addr <= 32'h0;
                    mtvec <= PROGADDR_IRQ;
                    instr_latch <= 32'h0;
                    dcsr <= 8'h0;
                    stap <= 32'h0;
                    tlb_clean <= 1'b0;
                    dbg_reg_write_resp <= 1'b0;
                    dbg_csr_we_resp <= 1'b0;
                end
                if(dbg_crs_reg_wr) begin
                    dbg_csr_we_resp <= 1'b1;
                    case(dbg_csr_reg_addr)
                    12'h7b0:begin//dcsr
                        dcsr[7:0] <= dbg_csr_data_in[7:0];//待写逻辑
                    end
                    12'h180:begin
                        stap <= dbg_csr_data_in;
                    end
                    12'h7b1:begin//dpc
                        dpc <= dbg_csr_data_in;//待写逻辑
                    end
                    12'h341:begin//mret_reg --> mepc
                        mret_reg <= dbg_csr_data_in;
                    end
                    12'h342:begin//mcause --> mcause
                        mcause <= dbg_csr_data_in;
                    end
                    12'h304:begin//irq_mask --> mie
                        irq_mask <= dbg_csr_data_in;
                    end
                    12'h305:begin
                        mtvec <= dbg_csr_data_in;
                    end
                    12'h300:begin//mstatus
                        mstatus <= dbg_csr_data_in;
                    end
                    endcase
                end
                else begin
                    case(dbg_csr_reg_addr)
                    12'h7b0:begin//dcsr
                        dbg_csr_data_out <= {24'b0,dcsr[7:0]};//待写逻辑
                    end
                    12'h180:begin
                        dbg_csr_data_out <= stap;
                    end
                    12'h7b1:begin//dpc
                        dbg_csr_data_out <= dpc;//待写逻辑
                    end
                    12'h341:begin//mret_reg --> mepc
                        dbg_csr_data_out <= mret_reg;
                    end
                    12'h342:begin//mcause --> mcause
                        dbg_csr_data_out <= mcause;
                    end
                    12'h304:begin//irq_mask --> mie
                        dbg_csr_data_out <= irq_mask;
                    end
                    12'h305:begin
                        dbg_csr_data_out <= mtvec;
                    end
                    12'h300:begin//mstatus
                        dbg_csr_data_out <= mstatus;
                    end
                    endcase
                end
                if(dbg_reg_write_req) begin
                    reg_wdata <= dbg_reg_wdata;
                    if(dbg_reg_waddr < 8'd32) begin
                        reg_we <= 1'b1;
                    end
                    dbg_reg_write_resp <= 1'b1;
                    if(dbg_reg_waddr == 8'd32) begin
                        core_pc <= dbg_reg_wdata;
                    end
                end
            end
        endcase
    end
    
end
endmodule
